﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;

namespace Mpi.Common
{
    public abstract class CustomProperty
    {

        protected bool _forcePredefinedValues;
        protected string _comment;
        protected string _name;
        protected Type _type;
        protected bool _passwordMask;

        public bool PasswordMask
        {
            get { return _passwordMask; }
            set { _passwordMask = value; }
        }
	

        public Type Type
        {
            get { return _type; }
        }


        public string Comment
        {
            get { return _comment; }
            set { _comment = value; }
        }

        public bool ForcePredefinedValues
        {
            get { return _forcePredefinedValues; }
            set { _forcePredefinedValues = value; }
        }

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public abstract void SetValue<T>(string val, Converter<string,T> conv);
        public abstract string GetValue();
        public abstract bool TryGetValue<T>(out T t);
        public abstract ReadOnlyCollection<object> PredefinedValues
        {
            get;
        }
        
    }

    public class CustomProperty<T> : CustomProperty where T : IComparable<T>
    {

        private T _val;
        private T _defaultVal;
        private List<object> _predefinedVals;


        public override ReadOnlyCollection<object> PredefinedValues
        {
            get 
            { 
                return new ReadOnlyCollection<object>(_predefinedVals);
            }
        }

        public T Default
        {
            get { return _defaultVal; }
            //set { defaultVal = value; }
        }

        public T Value
        {
            get { return _val; }
            set
            {
                if (base.ForcePredefinedValues && !_predefinedVals.Contains(value))
                    throw new ArgumentException("The value is not predefined while the force predefine property is enabled.");

                if (_val != null && !_val.Equals(value) || _val == null && value != null)
                {
                    _val = value;
                    OnValueChanged();
                }
            }
        }


        public CustomProperty()
        {
            _predefinedVals = new List<object>();
            _type = typeof(T);
            _defaultVal = default(T);

        }

        public CustomProperty(T defVal, IEnumerable<T> predefVals, bool forcePredefVals)
        {
            _predefinedVals = new List<object>();
            _type = typeof(T);
            
            _forcePredefinedValues = forcePredefVals;

            if (predefVals != null)
            {
                foreach (T t in predefVals)
                {
                    _predefinedVals.Add(t);
                }
            }
            Value = defVal;
            _defaultVal = defVal;
        }

        public event EventHandler ValueChanged;
        protected virtual void OnValueChanged()
        {
            if (ValueChanged != null)
                ValueChanged(this, new EventArgs());
        }

        public override void SetValue<S>(string val, Converter<string, S> conv)
        {
                Value = (T)(object)conv.Invoke(val);

        }

        public override string GetValue()
        {
            return _val.ToString();
        }

        public override bool TryGetValue<S>(out S s)
        {
            try
            {
                s = (S)(object)_val;
                return true;
            }
            catch
            {
                s = default(S);
                return false;
            }
        }


    }
}
